package scut.facerecognition.service.impl;

import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import jakarta.annotation.Resource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.reactive.function.client.ClientResponse;
import org.springframework.web.reactive.function.client.WebClient;
import scut.facerecognition.Utils.EncryptUtils;
import scut.facerecognition.Utils.UploadFileUtils;
import scut.facerecognition.constant.UserConstant;
import scut.facerecognition.entity.dto.EmailDTO;
import scut.facerecognition.entity.dto.RegisterDTO;
import scut.facerecognition.entity.pojo.User;
import scut.facerecognition.mapper.UserMapper;
import scut.facerecognition.result.Result;
import scut.facerecognition.service.UserService;
import scut.facerecognition.Utils.EmailUtils;


import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

@Service
public class UserServiceImpl implements UserService {
    @Resource
    private UserMapper userMapper;

    @Resource private WebClient.Builder webClientBuilder;

    @Resource private EmailUtils emailUtils;

    //注入redis操作模板
    @Resource private StringRedisTemplate stringRedisTemplate;

    /**
     * 注册
     * @param
     */
    public Result<String> register(MultipartFile file, String email, String password, String nickname, String sex,
                                   String birthday, String signature, String location, String school, String hobby) {
        //先判断用户是否已经注册
        if (userMapper.selectOne(new QueryWrapper<User>().eq("email", email)) != null) {
            return Result.error("用户已存在");
        }

        User user = new User();
        user.setEmail(email);
        String encryptPassword = EncryptUtils.encrypt(password);
        user.setPassword(encryptPassword);
        user.setNickname(nickname);
        user.setPhoto(UploadFileUtils.uploadFile(file, UserConstant.USER_PHOTO_ROOT_PATH));
        user.setSex(sex);
        user.setBirthday(birthday);
        user.setSignature(signature);
        user.setLocation(location);
        user.setSchool(school);
        user.setHobby(hobby);

        userMapper.insert(user);
        return Result.success("用户注册成功");
    }

    /**
     * 登陆
     * @param registerDTO
     * @return
     */
    public Result<SaTokenInfo> login(RegisterDTO registerDTO) {
       String email = registerDTO.getEmail();
       String password = registerDTO.getPassword();

       User user = userMapper.selectOne(new QueryWrapper<User>().eq("email", email));
       if (user == null) {
           return Result.error("用户不存在");
       }
       if(user.getPassword().equals(EncryptUtils.encrypt(password))){
           StpUtil.login(user.getId());
           return Result.success(StpUtil.getTokenInfo());
       }
       return Result.error("密码错误");
    }

    /**
     * 人脸识别
     * @param file
     * @return
     */
    public Result<String> faceRecognition(MultipartFile file) {
        String userId = StpUtil.getLoginIdAsString();
        String file1 = UploadFileUtils.uploadFile(file, UserConstant.USER_TEMP_PHOTO_PATH);
        String file2 = userMapper.selectOne(new QueryWrapper<User>().eq("id", userId)).getPhoto();

        //向python api发送请求
        String url = "http://localhost:5000/verify-by-path";
        // 构建请求体
        JSONObject requestJson = new JSONObject();
        requestJson.put("img1_path", file1);
        requestJson.put("img2_path", file2);

        ClientResponse response = null;
        try {
            // 发送 POST 请求并接收响应
            response = webClientBuilder.build()
                    .post()
                    .uri(url)
                    .header("Content-Type", "application/json")
                    .bodyValue(requestJson.toString())
                    .exchange()
                    .block();  // 阻塞直到响应返回
        } catch (Exception e) {
            e.printStackTrace();
        }

        return Result.success(response.bodyToMono(String.class).block());
    }
    /**
     * 更新用户信息
     * @param file
     * @param email
     * @param password
     * @param nickname
     * @return
     */
    public Result<String> updateUserInfo(MultipartFile file, String email, String password, String nickname, String sex,
                                         String birthday, String signature, String location, String school, String hobby) {
        //todo 是否要加入什么验证机制

        Long userId = StpUtil.getLoginIdAsLong();

        User user = new User();
        user.setId(userId);
        user.setPhoto(UploadFileUtils.uploadFile(file, UserConstant.USER_PHOTO_ROOT_PATH));
        user.setEmail(email);
        user.setPassword(EncryptUtils.encrypt(password));
        user.setNickname(nickname);
        user.setSex(sex);
        user.setBirthday(birthday);
        user.setSignature(signature);
        user.setLocation(location);
        user.setSchool(school);
        user.setHobby(hobby);

        userMapper.updateById(user);
        return Result.success("用户信息更新成功");
    }

    /**
     * 获取用户信息
     * @return
     */
    public Result<User> getUserInfo() {
        String userId = StpUtil.getLoginIdAsString();
        User user = userMapper.selectOne(new QueryWrapper<User>().eq("id", userId));
        return Result.success(user);
    }

    /**
     * 发送验证码
     * @param emailDTO
     * @return
     */
    public Result<String> sendCode(EmailDTO emailDTO) {
        //获得接收方的邮箱
        String email = emailDTO.getEmail();

        Map<String, Object> map = new HashMap<>();
        //随机生成六位验证码
        String code = String.valueOf((int)((Math.random()*9+1)*100000));
        //将验证码存入redis中 1min后过期
        stringRedisTemplate.opsForValue().set(email+"验证码", code, 1, TimeUnit.MINUTES);

        map.put("content", code);
        EmailDTO message = EmailDTO.builder()
                .template("common.html")
                .email(email)
                .subject("用户注册")
                .commentMap(map).build();
        CompletableFuture.runAsync(()-> emailUtils.sendHtmlMail(message));
        //todo 能不能直接返回给前端，前端存储，自己验证
        return Result.success(code);
    }

    /**
     * 验证验证码
     * @param emailDTO
     * @return
     */
    public Result<String> verifyCode(EmailDTO emailDTO) {
        String verifyCode = emailDTO.getVerifyCode();
        String email = emailDTO.getEmail();
        if (stringRedisTemplate.opsForValue().get(email+"验证码").equals(verifyCode)) {
            return Result.success("验证码正确");
        } else {
            return Result.error("验证码错误");
        }

    }

    @Override
    public Result<User> getOtherInfo(RegisterDTO registerDTO) {
        //在数据库中查询nickname为nickname的用户
        String nickname = registerDTO.getNickname();
        User user = userMapper.selectOne(new QueryWrapper<User>().eq("nickname", nickname));
        if (user == null) {
            return Result.error("用户不存在");
        }
        return Result.success(user);
    }
}
